<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use MongoDB\BSON\UTCDateTime;
use ErrorException;
use App\Models\Factory\Mongo\DcsData AS FactoryDcsData;       //电厂数据模型
use App\Models\Local\DcsData AS LocalDcsData;   //本地数据模型
use Carbon\Carbon;
use Log;

/**
 * 从电厂获取DCS数据并保存到本地
 */
class DcsDataJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $timeout = 180; //队列超时时间
    protected $datetime;
    protected $factory_conn; //电厂连接
    protected $local_conn; //本地连接
    protected $factory_data_table; //电厂保存的MongoDB原始数据集合
    protected $local_data_table; //本地保存的格式化后的数据集合
    public $tries = 3;

    /**
     *
     * @return void
     */
    public function __construct($params=null)
    {
        $this->datetime = $params && isset($params['datetime']) ? $params['datetime'] : '';
        $this->factory_conn = $params && isset($params['factory_conn']) ? $params['factory_conn'] : '';
        $this->local_conn = $params && isset($params['local_conn']) ? $params['local_conn'] : '';
        $this->factory_data_table = $params && isset($params['factory_data_table']) ? $params['factory_data_table'] : '';
        $this->local_data_table = $params && isset($params['local_data_table']) ? $params['local_data_table'] : '';
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $this->mongodb_data();
    }

    //从远程MongoDB获取数据（historian5.5读取不方便转为opc读取并转存到电厂本地MongoDB）
    protected function mongodb_data(){
        try{
            $factoryDcsData = (new FactoryDcsData())->setConnection($this->factory_conn)->setTable($this->factory_data_table);  //连接电厂内部数据库
            $localDcsData = (new LocalDcsData())->setConnection($this->local_conn)->setTable($this->local_data_table);      //连接本地数据库表

            $begin = date('Y-m-d H:i', strtotime($this->datetime)) . ':00'; //获取1min内的数据
            $end = date('Y-m-d H:i', strtotime($this->datetime)) . ':59';
            $start = new UTCDateTime(strtotime($begin)*1000);
            $stop = new UTCDateTime(strtotime($end)*1000);
            $configTags = config('hqtags.tags');
            $tags = [];
            foreach($configTags as $tag =>$name){
                $tags[] = $tag;
            }

            $obj = $factoryDcsData->select(['tag_name', 'datetime', 'value'])->whereBetween('datetime', array($start, $stop));
            if(count($tags) > 0){
                $obj = $obj->whereIn("tag_name", $tags);
            }
            
            $obj->chunk(100, function ($rows) use ($localDcsData) {
                $params = [];
                $stack = [];
                if($rows && count($rows) > 0){
                    foreach ($rows as $key => $item) {
                        if(in_array($item->tag_name, $stack)){
                            continue;
                        }

                        $stack[] = $item->tag_name;
                        //$carbonDate = Carbon::instance($item->datetime->toDateTime());
                        //$datetime = $carbonDate->toDateTimeString();
                        $local_row = $localDcsData->findRowByTagAndTime($item->tag_name, $this->datetime);
                        if(!$local_row){
                            //本地不存在则插入
                            $params[] = array(
                                'tag_name' => $item->tag_name,
                                'value'=> $item->value,
                                'flag'=> 0,
                                'datetime'=> $this->datetime
                            );
                        }
                    }
                }

                if(count($params) > 0){
                    $localDcsData->insertMany($params);
                    Log::info($this->datetime . '历史数据库数据插入本地成功'.count($params).'条');
                }
                else{
                    Log::info($this->datetime . '历史数据库没有数据插入');
                }
            });
        }
        catch(ErrorException $ex){
            Log::info('连接电厂历史数据库异常');
            Log::info(var_export($ex->getMessage(), true));
        }
    }

}
